#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#ifdef WIN32
#include "windows.h"
#else
#include <sys/time.h>
#include <time.h>
#endif
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "stdarg.h"
#include "math.h"
#include "assert.h"

#include "BList.h"

#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"
#include "Ufeatureterm.h"
#include "AUfeatureterm.h"
#include "FT_refinement.h"
#include "FT_generalization.h"



#ifndef WIN32
struct timeval init_tick_count_value;

void setupTickCount()
{
	gettimeofday(&init_tick_count_value, NULL);
}

long GetTickCount()
{
	struct timeval now;
	gettimeofday(&now, NULL);
	struct timeval diff;
	diff.tv_sec = now.tv_sec - init_tick_count_value.tv_sec;
	diff.tv_usec = now.tv_usec - init_tick_count_value.tv_usec;
	if (diff.tv_usec < 0)
	{
		diff.tv_sec--;
		diff.tv_usec+=1000000;
	}
	return diff.tv_sec*1000 + diff.tv_usec/1000;
}
#endif



int main(void)
{
	int t_start,t_end;

#ifndef WIN32
	setupTickCount();
#endif

	Ontology *o=new Ontology();
	FTKBase *case_base=new FTKBase(o);
	FTKBase *domain_model=new FTKBase(o);

	domain_model->create_boolean_objects(o);
	case_base->uses(domain_model);

	printf("Stats 0: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());

	{
/*
		domain_model->ImportNOOS("../NOOS/robots-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/robots-dm.noos",o);
		case_base->ImportNOOS("../NOOS/robots-cases-6.noos",o);
*/

/*
		domain_model->ImportNOOS("../NOOS/trains-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/trains-dm.noos",o);
		case_base->ImportNOOS("../NOOS/trains-cases-10.noos",o);
*/

/*
		domain_model->ImportNOOS("../NOOS/family-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/family-dm.noos",o);
		case_base->ImportNOOS("../NOOS/family-cases-12.noos",o);
//		case_base->ImportNOOS("../NOOS/family-cases-12-sets.noos",o);
*/

/*
		domain_model->ImportNOOS("../NOOS/zoology-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/zoology-DM.noos",o);
		case_base->ImportNOOS("../NOOS/zoology-cases-101.noos",o);
*/

/*
		domain_model->ImportNOOS("../NOOS/monks-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/monks-DM.noos",o);
		case_base->ImportNOOS("../NOOS/monks-1-train.noos",o);
//		case_base->ImportNOOS("../NOOS/monks-2-train.noos",o);
//		case_base->ImportNOOS("../NOOS/monks-3-train.noos",o);
*/

/*
		domain_model->ImportNOOS("../NOOS/soybean-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/soybean-dm.noos",o);
		case_base->ImportNOOS("../NOOS/soybean-cases-307.noos",o);
*/


		domain_model->ImportNOOS("../NOOS/sponge-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/sponge-dm.noos",o);
//		case_base->ImportNOOS("../NOOS/sponge-cases-503.noos",o);
//		case_base->ImportNOOS("../NOOS/sponge-cases-280.noos",o);
//		case_base->ImportNOOS("../NOOS/sponge-cases-120.noos",o);
		case_base->ImportNOOS("../NOOS/sponge-cases-test.noos",o);


/*
//      OLD FILES: --------------------------------------------------------------------
		domain_model->ImportNOOS("../NOOS/toxicology-eva/toxicology-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/toxicology-eva/toxicology-dm.noos",o);
		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-descriptions.noos",o);
//		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-descriptions-50.noos",o);
		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-problems.noos",o);
		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-cases-502.noos",o);
//		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-cases-50.noos",o);
*/

/*
//      NEW FILES: --------------------------------------------------------------------
		domain_model->ImportNOOS("../NOOS/toxic-eva-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/toxic-eva-dm.noos",o);
//		case_base->ImportNOOS("../NOOS/toxic-eva-cases-10.noos",o);
//		case_base->ImportNOOS("../NOOS/toxic-eva-cases-50.noos",o);
		case_base->ImportNOOS("../NOOS/toxic-eva-cases-100.noos",o);
//		case_base->ImportNOOS("../NOOS/toxic-eva-cases-371.noos",o);
*/

/*
		domain_model->ImportNOOS("blending-ontology.noos",o);
		case_base->ImportNOOS("blending-cases.noos",o);
*/

		printf("Stats 1: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());

		printf("There are %i + %i undefined terms.\n",domain_model->get_n_undefined_terms(),case_base->get_n_undefined_terms());
		domain_model->print_undefined_terms();
		case_base->print_undefined_terms();

		t_start=GetTickCount();

		{
			FeatureTerm *f1;
			FeatureTerm *f2;
			FeatureTerm *f;
			List<FeatureTerm> *unifications,*antiunifications;
/*
			//	Integers:
			f1->fromStringNOOS("(define (integer))",case_base,o);
			f2->fromStringNOOS("1",case_base,o);
*/
/*
			//	Floats:
			f1->fromStringNOOS("(define (number))",case_base,o);
			f2->fromStringNOOS("1.0",case_base,o);
*/
/*
			//	Symbols:
			f1->fromStringNOOS("(define (symbol))",case_base,o);
			f2->fromStringNOOS("\"hola\"",case_base,o);
*/
/*
			// Example 1: (simple, 1 unification)
			f1->fromStringNOOS("(define (person) "
							   "  (father (define (male)))"
							   ")",case_base,o);
			f2->fromStringNOOS("(define (female) "
							   "  (father (define (person)))"
							   ")",case_base,o);
*/
/*
			// Example 2: (nested, 2 possible unification)
			f1->fromStringNOOS("(define (person) "
							   "  (son (define (male)))"
							   ")",case_base,o);
			f2->fromStringNOOS("(define (female) "
							   "  (son (define (person) (son (define (male))))))"
							   ")",case_base,o);
*/

/*
			// Example 3: (nested, 3 possible unifications)
			f1->fromStringNOOS("(define (person) "
							   "  (son (define (male) "
							   "         (wife (define (female)) )) "
							   "       (define (male)))"
							   ")",case_base,o);
			f2->fromStringNOOS("(define (female) "
							   "  (son (define (person) "
							   "         (son (define (male)))))"
							   ")",case_base,o);
*/

			// Example 4: (nested, variable equality, 1 possible unifications)
/*
			f1=FeatureTerm::fromStringNOOS("(define ?X1 (male) "
							   "  (son (define (male) "
							   "         (father !X1)) "
							   "  ) "
							   ") ",case_base,o);
			f2=FeatureTerm::fromStringNOOS("(define (male) "
							   ") ",case_base,o);
*/

			// Example 5: (nested, variable equality, 1 possible unifications)
/*
			f1=FeatureTerm::fromStringNOOS("(define ?X1 (male) "
							   "  (son (define (male) "
							   "         (wife (define (female))) "
							   "         (father !X1)) "
							   "  ) "
							   ") ",case_base,o);
			f2=FeatureTerm::fromStringNOOS("(define (male) "
							   "  (son (define (male) "
							   "         (father (define (male)))) "
							   "  ) "
							   ") ",case_base,o);
*/

			// Example 6: (nested, double variable equality, 4 possible unifications)
/*
			f1=FeatureTerm::fromStringNOOS("(define (person) "
							   "  (son (define ?X1 (male))) "
							   "  (father !X1) "
							   ") ",case_base,o);
			f2=FeatureTerm::fromStringNOOS("(define (male) "
							   "  (son (define (male) "
							   "         (father (define (male))))) "
							   "  (father (define (male) "
							   "            (mother (define (female))))) "
							   ") ",case_base,o);
*/

			// Example 7: (path equality in sets, 1 possible unification)
/*
			f1=FeatureTerm::fromStringNOOS("(define (person) "
									       "  (son (define (male))) "
										   ") ",case_base,o);
			f2=FeatureTerm::fromStringNOOS("(define (male) "
										   "  (son (define ?X1 (set))) "
										   "  (father !X1) "
										   ") ",case_base,o);
*/		

/*
			{
				Symbol *s = new Symbol("concept-l1");
				List<FeatureTerm> *l = case_base->SearchFT(s);
				f1 = new FeatureTerm(l->operator[](0));
				l->ExtractAll();
				delete l;
				delete s;
				s = new Symbol("concept-l2");
				l = case_base->SearchFT(s);
				f2 = new FeatureTerm(l->operator[](0));
				l->ExtractAll();
				delete l;
				delete s;
			}

			{
					char *s;
					s=f1->toStringNOOS(domain_model);
					printf("F1:\n%s\n",s);
					delete []s;
					s=f2->toStringNOOS(domain_model);
					printf("F2:\n%s\n",s);
					delete []s;
			}

			unifications=unification(f1,f2,o,domain_model);
			if (unifications!=0 && !unifications->EmptyP()) {
				printf("Unification successful!\n");
				printf("%i unifications:\n",unifications->Length());
				unifications->Rewind();
				while(unifications->Iterate(f)) {
					char *s;
					s=f->toStringNOOS(domain_model);
					printf("%s\n",s);
					delete []s;
				} // while 
			} else {
				printf("Unification failed!\n");
			} // if 


			if (unifications!=0) delete unifications;
*/

/*
			{
				List<FeatureTerm> *l = new List<FeatureTerm>;
				l->Add(f1);
				l->Add(f2);
				antiunifications = new List<FeatureTerm>;
				antiunification(antiunifications,l,SPECIALIZATION_LANGUAGE_L2,0,o,domain_model,true,AU_VERSION_FAST);
				l->ExtractAll();
				delete l;
			}
			if (antiunifications!=0 && !antiunifications->EmptyP()) {
				printf("Antiunification successful!\n");
				printf("%i antiunifications:\n",antiunifications->Length());
				antiunifications->Rewind();
				while(antiunifications->Iterate(f)) {
					char *s;
					s=f->toStringNOOS(domain_model);
					printf("%s\n",s);
					delete []s;
				} // while 
			} else {
				printf("Antiunification failed!\n");
			} // if 

			delete f1;
			delete f2;
			if (antiunifications!=0) delete antiunifications;
*/

			//	Subsumption:
			char *s1=
" (define (sponge) "
"  (spiculate-skeleton (define (spiculate-skeleton) "
"                        (megascleres (define (megascleres) "
"                                       (smooth-form (define (megas-form :id oxea))) "
"                                       (characteristics (define (characters) "
"                                                          (shaft (define (shaft :id fusiform))))))) "
"                        (chemical (define (chemical :id silica))) "
"                        (microscleres (define (micros :id absent-microscleres)))))) ";
			char *s2=
" (define (sponge :id sponge-48) "
"  (external-features (define (external-features) "
"                       (body-size (define (body-size :id medium))) "
"                       (consistency (define (consistency :id soft))) " 
"                       (hand (define (hand :id crumbled))) "
"                       (growing (define (growing) "
"                                  (line-form (define (line-form) "
"                                               (form (define (form :id sheet))) " 
"                                               (peduncle (define ?X9 (new-boolean :id no))))))) "
"                       (brush !X9) "
"                       (osc (define (osc-characteristics) "
"                              (dot (define ?X11 (new-boolean :id yes))) "
"                              (numosc (define (numosc :id several))))))) "
"  (ecological-features (define (ecological-features) "
"                         (fixation (define (fixation :id not-fixed))) "
"                         (location (define (sea :id mediterranean))))) " 
"  (spiculate-skeleton (define (spiculate-skeleton) "
"                        (chemical (define (chemical :id silica))) "
"                        (architecture (define (architecture :id perifery-radiate))) "
"                        (megascleres (define (megascleres) "
"                                       (smooth-form (define (set) "
"                                                      (define (megas-form :id oxea)) "
"                                                      (define (triaena :id plagiotriaena)))) "
"                                       (acanthose (define (acanthose :id no-acanthose))) "
"                                       (characteristics (define (characters) "
"                                                          (shaft (define (shaft :id fusiform))))) "
"                                       (ornamentation (define (ornamentation :id smooth-ornamentation))) "
"                                       (styloids !X9) "
"                                       (predominant-kind (define (predominancy :id oxeas))) "
"                                       (max-length 6500) "
"                                       (two-or-more-length !X11))) " 
"                        (microscleres (define (set) " 
"                                        (define (microxea) "
"                                         (max-length 6500)) "
"                                        (define (aster :id spiraster)) "
"                                        (define (aster :id metaster)))) "
"                        (sclerospongids !X9) "
"                        (uniform-length !X9))) "
"  (anatomy (define (anatomic-features) "
"             (ornamentation (define (ornamentation :id spines)))))) ";

			f1 = FeatureTerm::fromStringNOOS(s1,domain_model,o);
			f2 = FeatureTerm::fromStringNOOS(s2,domain_model,o);

			if (f1->subsumes(f2)) {
				printf("f1 subsumes f2\n");
			} else {
				printf("f1 does not subsume f2\n");
			} // if  

			delete f1;
			delete f2;
		}

		t_end=GetTickCount();

		printf("Time taken: %i\n",t_end-t_start);

		printf("Stats 2: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());
	}

	delete case_base;
	delete domain_model;

	printf("Stats 3: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());

	delete o;

	printf("Stats 4: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());
	Symbol::stats_printSymbolStats();

	Symbol::reset();

	return 0;
} /* main */ 





